﻿#include "Server.h" // Winsock2的头文件必须定义在winsock.h、windows.h之前
#include <iostream>
#include <Windows.h>
#include <iostream>
#include <winbase.h>


#include "md5file.h"
#include "HLog.h"
using namespace std;
/// <summary>
/// 同步锁对象
/// </summary>
CRITICAL_SECTION g_cs;

/// <summary>
/// 项目信息
/// </summary>
extern std::vector<VERSIONINFO> g_VersionList;

/// <summary>
/// 进程唯一
/// </summary>
bool Unique()
{
	HANDLE hMutex = CreateMutex(NULL, true, L"ChyUpdater-Server");
	if (GetLastError() == ERROR_ALREADY_EXISTS) {
		if (hMutex) CloseHandle(hMutex);
		MessageBox(0, L"ChyUpdater-Server already execute", L"Note", 0);
		return false;
	}
	return true;
}


char g_exeDirPath[300];				// exe文件所在目录
std::vector<std::string> g_portList;// 服务端监听的端口列表

/// <summary>
/// 初始化项目信息列表
/// </summary>
void initProjectInfo() 
{
	printf("Init Project Info List...\n");

	// 获取所有项目文件夹
	vector<string> directoryList = FileHelper::TraversalDirectory(g_exeDirPath);

	// 构造项目详细信息（文件路径、文件MD5值）
	for (size_t i = 0; i < directoryList.size(); i++)
	{

		// 截取项目名
		int projectNameIndex = directoryList[i].find_last_of("\\");
		std::string projectName = directoryList[i].substr(projectNameIndex + 1, directoryList[i].size() - projectNameIndex - 1);
		printf("Load Project ：%s\t\n", projectName.data());

		// 获取文件路径
		vector<string> filePathList = FileHelper::TraversalFile(directoryList[i].data());

		// 获取文件MD5
		vector<string> MD5List;
		for (size_t i = 0; i < filePathList.size(); i++)
		{
			//printf("【Server】计算MD5值：%s\n", filePathList[i].data());
			MD5List.push_back(getFileMD5(filePathList[i]));
		}

		// 构造结构体
		VERSIONINFO versionInfo;
		versionInfo.ProjectName = projectName;
		versionInfo.FileList = filePathList;
		versionInfo.MD5List = MD5List;
		g_VersionList.push_back(versionInfo);

		// 去除文件路径中的项目名称
		for (size_t i = 0; i < versionInfo.FileList.size(); i++) {
			int index = versionInfo.FileList[i].find(projectName);
			versionInfo.FileList[i] = versionInfo.FileList[i].substr(index + projectName.size() + 1);
		}
	}
}

int main(int argc, char* argv[])
{
	// 进程唯一
	if (false == Unique()) { return 0; }

	// 获取exe全路径、exe所在目录
	char* exePath = argv[0];
	memset(g_exeDirPath, 0, sizeof(g_exeDirPath));
	strncpy(g_exeDirPath, exePath, strrchr(exePath, '\\') - exePath);

	//
	// 使用宏命令先隐藏控制台，再根据配置文件决定是否显示控制台
	//

#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址
	int isDebug = 0;
	FILE* pFile = fopen((std::string(g_exeDirPath) + "//Server.config").data(), "r+"); // Opens for both reading and writing. The file must exist.
	std::string portListStr;
	if (pFile == NULL) {
		pFile = fopen((std::string(g_exeDirPath) + "//Server.config").data(), "w+");
		if (pFile == NULL) { return 0; }
		//读取端口号、DEBUG模式
		portListStr = "9966|4899";
		isDebug = 0;
		fprintf(pFile, "isDebug=%d\nport=%s", isDebug, portListStr.data());
		fclose(pFile);
	}
	else {
		char tempStr[200]; memset(tempStr, 0, sizeof(tempStr));
		fscanf(pFile, "isDebug=%d\nport=%s", &isDebug, tempStr);
		portListStr = tempStr;
		fclose(pFile);
	}
	int begin = 0;
	while (true)
	{
		int end = portListStr.find("|", begin);
		if (end == -1) { g_portList.push_back(portListStr.substr(begin, -1)); break; }
		else { g_portList.push_back(portListStr.substr(begin, end - begin)); }
		begin = end + 1;
	}
	if (isDebug)
	{
		AllocConsole(); //创建控制台
		freopen("conout$", "w", stdout); //将系统的标准输出设备【stdout】重定向到当前打开的控制台
	}


	// 初始化全局同步锁对象
	InitializeCriticalSection(&g_cs);

	//
	// 初始化项目详细信息列表
	//
	initProjectInfo();

	// 启动服务器
	HLog::Logging(HLog::INFO, "\t*********【ChyUpdater - Server】***********");
	ServerStart();

	// 主线程不能退出
	while (true) { Sleep(50); }
}